﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace Chip8Dev.CPU
{
    public sealed partial class Interpreter : ICpuEngine
    {
        private void Opcode_ADD_7(Instruction inst)
        {
            DebugWrite(String.Format("V{0:2X} = V{0:2X} + {1:2X}", inst.X, inst.KK));

            /* Must wrap in order to emulate the 8bit limit */
            m_State.VRegisters[inst.X] += inst.KK;
            ByteOverflowFix(inst.X);
        }

        private void Opcode_OR(Instruction inst)
        {
            DebugWrite(String.Format("V{0:2X} = V{0:2X} | V{1:2X}", inst.X, inst.Y));

            m_State.VRegisters[inst.X] |= m_State.VRegisters[inst.Y];
            ClearOverflowFix();
        }

        private void Opcode_AND(Instruction inst)
        {
            DebugWrite(String.Format("V{0:2X} = V{0:2X} & V{1:2X}", inst.X, inst.Y));

            m_State.VRegisters[inst.X] &= m_State.VRegisters[inst.Y];
            ClearOverflowFix();
        }

        private void Opcode_XOR(Instruction inst)
        {
            DebugWrite(String.Format("V{0:2X} = V{0:2X} ^ V{1:2X}", inst.X, inst.Y));

            m_State.VRegisters[inst.X] ^= m_State.VRegisters[inst.Y];
            ClearOverflowFix();
        }

        private void Opcode_ADD_8(Instruction inst)
        {
            DebugWrite(String.Format("V{0:2X} = V{0:2X} + V{1:2X} with carry", inst.X, inst.Y));

            Int32 result = m_State.VRegisters[inst.X] + m_State.VRegisters[inst.Y];
            m_State.VRegisters[0xF] = result > Byte.MaxValue ? 1 : 0;
        }

        private void Opcode_SUB(Instruction inst)
        {
            DebugWrite(String.Format("V{0:2X} = V{0:2X} - V{1:2X} with carry", inst.X, inst.Y));

            m_State.VRegisters[0xF] = m_State.VRegisters[inst.X] > m_State.VRegisters[inst.Y] ? 1 : 0;
            m_State.VRegisters[inst.X] -= m_State.VRegisters[inst.Y];
        }

        private void Opcode_SUBN(Instruction inst)
        {
            DebugWrite(String.Format("V{0:2X} = V{1:2X} - V{0:2X} with carry", inst.X, inst.Y));

            m_State.VRegisters[0xF] = m_State.VRegisters[inst.Y] > m_State.VRegisters[inst.X] ? 1 : 0;
            m_State.VRegisters[inst.Y] -= m_State.VRegisters[inst.X];
        }

        private void Opcode_SHR(Instruction inst)
        {
            DebugWrite(String.Format("V{0:2X} = V{0:2X} >> 1", inst.X, inst.Y));

            m_State.VRegisters[0xF] = m_State.VRegisters[inst.X] & 1;
            m_State.VRegisters[inst.X] >>= 1;
        }

        private void Opcode_SHL(Instruction inst)
        {
            DebugWrite(String.Format("V{0:2X} = V{0:2X} << 1", inst.X, inst.Y));

            m_State.VRegisters[0xF] = (m_State.VRegisters[inst.X] & 80) >> 7;
            m_State.VRegisters[inst.X] <<= 1;
        }


    }
}
